package com.dldata.devtools30.controller.metadata;

import com.dldata.devtools30.common.EnumUtils;
import com.dldata.devtools30.controller.DevBase30Controller;
import com.dldata.devtools30.entity.DevtModelMetadataFieldEntity;
import com.dldata.devtools30.entity.DevtModelMetadataTableEntity;
import com.dldata.devtools30.entity.DevtModelMetadataTypeEntity;
import com.dldata.devtools30.repository.common.DlBaseJdbcTemplate;
import com.dldata.devtools30.service.metadata.DevtModelMetadataFieldService;
import com.dldata.devtools30.service.metadata.DevtModelMetadataTableService;
import com.dldata.devtools30.service.metadata.DevtModelMetadataTypeService;
import com.dldata.devtools30.utils.DBTypeUtil;
import com.dldata.devtools30.utils.Result;
import com.dldata.devtools30.utils.StringUtil;
import com.dldata.devtools30.utils.dataexport.DataExportUtil;
import com.dldata.devtools30.utils.dataexport.TableConfig;
import com.dldata.devtools30.utils.dbtable.DbTableManager;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Controller
@RequestMapping(value = "/DevtModelMetadataTableController")
public class DevtModelMetadataTableController extends DevBase30Controller {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    DevtModelMetadataTableService metadataTableService;

    @Autowired
    DevtModelMetadataFieldService metadataFieldService;

    @Autowired
    DevtModelMetadataTypeService metadataTypeService;

    @Autowired
    DlBaseJdbcTemplate dlBaseJdbcTemplate;
    
    
    
    @RequestMapping(value = "/getAllResTreeGrid")
    @ResponseBody
    public Result getAllResTreeGrid(@RequestParam Map<String, String> paramMap){
        String serach =paramMap.get("serach");
        String typeid =paramMap.get("typeid");
        List<String> modeltype =StringUtil.isEmptyOrLength0(paramMap.get("modeltype"))?new ArrayList():Arrays.asList(paramMap.get("modeltype").split(","));
        if(modeltype.size()==0){
            EnumUtils.ModelTypeEnum[] values = EnumUtils.ModelTypeEnum.values();
            for (int i = 0; i < values.length; i++) {
                EnumUtils.ModelTypeEnum value = values[i];
                modeltype.add(value.name());
            }
        }
        
        List<DevtModelMetadataTableEntity> metadataTableEntities =(StringUtil.isEmptyOrLength0(serach)&&StringUtil.isEmptyOrLength0(typeid))?
                metadataTableService.getAll(modeltype):
                (StringUtil.isEmptyOrLength0(typeid)?metadataTableService.getAll(typeid,serach,modeltype):metadataTableService.getAll(typeid,modeltype));
        List<DevtModelMetadataTypeEntity> metadataTypeEntities= metadataTypeService.getAll();
        List<Map> list=new ArrayList<>();
        for (int i = 0; i < metadataTypeEntities.size(); i++) {
            DevtModelMetadataTypeEntity sysModelMetadataTypeEntity = metadataTypeEntities.get(i);
            Map<String,Object> map=new HashMap<>();
            map.put("id",sysModelMetadataTypeEntity.getId());
            map.put("flmc",sysModelMetadataTypeEntity.getFlmc());
            map.put("name",sysModelMetadataTypeEntity.getFlmc());
            map.put("code",sysModelMetadataTypeEntity.getFlmc());
            map.put("typeId",sysModelMetadataTypeEntity.getId());
            map.put("pId","0");
            list.add(map);
        }
        for(DevtModelMetadataTableEntity tableEntity:metadataTableEntities){
            Map<String,Object> map=new HashMap<>();
            map.put("id",tableEntity.getId());
            map.put("xh",tableEntity.getXh());
            map.put("code",tableEntity.getCode());
            map.put("name",tableEntity.getName());
            map.put("typeId",tableEntity.getTypeId());
            map.put("bz",tableEntity.getBz());
            map.put("viewcode",tableEntity.getViewcode());
            map.put("flmc","");
            metadataTypeEntities.stream().filter(f->f.getId().equals(tableEntity.getTypeId())).forEach(m->{
                map.put("flmc",m.getFlmc());
            });
            map.put("pId",tableEntity.getTypeId());
            list.add(map);
        }
        
        return Result.ok(list);
    }

    @RequestMapping(value = "/getAll")
    @ResponseBody
    public Result getAll(@RequestParam Map<String, String> paramMap){
        String serach =paramMap.get("serach");
        String typeid =paramMap.get("typeid");
        List<String> modeltype =StringUtil.isEmptyOrLength0(paramMap.get("modeltype"))?new ArrayList():Arrays.asList(paramMap.get("modeltype").split(","));
        if(modeltype.size()==0){
            EnumUtils.ModelTypeEnum[] values = EnumUtils.ModelTypeEnum.values();
            for (int i = 0; i < values.length; i++) {
                EnumUtils.ModelTypeEnum value = values[i];
                modeltype.add(value.name());
            }
        }

        List<DevtModelMetadataTableEntity> metadataTableEntities =(StringUtil.isEmptyOrLength0(serach)&&StringUtil.isEmptyOrLength0(typeid))?
                metadataTableService.getAll(modeltype):
                (StringUtil.isEmptyOrLength0(typeid)?metadataTableService.getAll(typeid,serach,modeltype):metadataTableService.getAll(typeid,modeltype));
        List<DevtModelMetadataTypeEntity> metadataTypeEntities= metadataTypeService.getAll();
        List<Map> list=new ArrayList<>();
        for(DevtModelMetadataTableEntity tableEntity:metadataTableEntities){
            Map<String,Object> map=new HashMap<>();
            map.put("id",tableEntity.getId());
            map.put("xh",tableEntity.getXh());
            map.put("code",tableEntity.getCode());
            map.put("name",tableEntity.getName());
            map.put("typeId",tableEntity.getTypeId());
            map.put("bz",tableEntity.getBz());;
            map.put("modeltype",tableEntity.getModeltype());
            map.put("viewcode",tableEntity.getViewcode());
            map.put("flmc","");
            metadataTypeEntities.stream().filter(f->f.getId().equals(tableEntity.getTypeId())).forEach(m->{
                map.put("flmc",m.getFlmc());
            });
            list.add(map);
        }

        return Result.ok(list);
    }

    @RequestMapping(value = "/save")
    @ResponseBody
    public Result save(DevtModelMetadataTableEntity entity){
        if(StringUtil.isEmptyOrLength0(entity.getName())){
            return Result.error("表名不能为空");
        }
        if(StringUtil.isEmptyOrLength0(entity.getCode())){
            return Result.error("字段代码不能为空");
        }
        if(StringUtil.isEmptyOrLength0(entity.getTypeId())){
            return Result.error("请选择所属分类");
        }
        DevtModelMetadataFieldEntity fieldEntity=null;
        DevtModelMetadataFieldEntity fieldDataEntity=null;
        if(StringUtil.isEmptyOrLength0(entity.getId())){
            entity.setId(UUID.randomUUID().toString());
            fieldEntity = new DevtModelMetadataFieldEntity();
            fieldEntity.setBz("ID主键");
            fieldEntity.setFieldType(EnumUtils.FIELDTYPE.STRING.getCode());
            fieldEntity.setFieldName("ID");
            fieldEntity.setFieldCode("ID");
            fieldEntity.setFormId(entity.getId());
            fieldEntity.setId(UUID.randomUUID().toString());
            fieldEntity.setPkey(1);
            fieldEntity.setTypeZeroLength(0);
            fieldEntity.setTypeLength(64);
            fieldEntity.setXh(1);

            fieldDataEntity = new DevtModelMetadataFieldEntity();
            fieldDataEntity.setBz("数据时间");
            fieldDataEntity.setFieldType(EnumUtils.FIELDTYPE.DATE.getCode());
            fieldDataEntity.setFieldName("数据时间");
            fieldDataEntity.setFieldCode("datatime");
            fieldDataEntity.setFormId(entity.getId());
            fieldDataEntity.setId(UUID.randomUUID().toString());
            fieldDataEntity.setPkey(0);
            fieldDataEntity.setTypeZeroLength(0);
            fieldDataEntity.setTypeLength(0);
            fieldDataEntity.setXh(2);
        }

        List<DevtModelMetadataTableEntity> tableEntities=  commonApiDao.getScrollData(DevtModelMetadataTableEntity.class).getResultlist();
        for (int i = 0; i < tableEntities.size(); i++) {
            DevtModelMetadataTableEntity metadataTableEntity = tableEntities.get(i);
            if(metadataTableEntity.getCode().equalsIgnoreCase(entity.getCode())&&!metadataTableEntity.getId().equalsIgnoreCase(entity.getId())){
                return Result.error("表代码重复！");
            }
            if(metadataTableEntity.getXh().equals(entity.getXh()) && !metadataTableEntity.getId().equalsIgnoreCase(entity.getId())){
                return Result.error("表序号重复！");
            }
        }
        entity.setCode(entity.getCode().toUpperCase());
        entity.setViewcode("V_"+entity.getCode());

        metadataTableService.save(entity);
        if(fieldEntity!=null){
            metadataFieldService.save(fieldEntity);
        }
        if(fieldDataEntity!=null){
            metadataFieldService.save(fieldDataEntity);
        }

        return Result.ok();
    }

    @RequestMapping(value = "/delete")
    @ResponseBody
    public Result delete(@RequestParam Map<String, String> paramMap){

        String idt =paramMap.get("id");
        if(StringUtil.isEmptyOrLength0(idt)){
            return  Result.error("参数有误");
        }
        try {
            String[] split = idt.split(",");
            for (int j = 0; j < split.length; j++) {
                String tableid = split[j];
                metadataTableService.deleteOne(tableid);
                List<DevtModelMetadataFieldEntity> metadataFieldEntities= metadataFieldService.getAllByTid( tableid);
                for (int i = 0; i < metadataFieldEntities.size(); i++) {
                    DevtModelMetadataFieldEntity entity = metadataFieldEntities.get(i);
                    metadataFieldService.deleteOne(entity.getId());
                }
            }
        }
        catch (Exception ex){

            logger.error("【执行"+this.getClass().getName()+".delete() 方法失败 】异常："+ex.getMessage(),ex);
            return  Result.error("操作错误，请稍候再试!");
        }
        return  Result.ok("删除成功");
    }
    
    @RequestMapping(value = "/export")
    public void export(@RequestParam Map<String, String> paramMap, HttpServletResponse response) throws Exception {

        String tableidlist = paramMap.get("tableidlist");
        if(!StringUtil.isEmptyOrLength0(tableidlist)&&tableidlist.endsWith(",")){
            tableidlist=tableidlist.substring(0,tableidlist.length()-1);
        }
        String[] split = tableidlist.split(",");

        TableConfig tableConfig=new TableConfig("devt_model_metadata_table","元数据表基础配置表","id","",Boolean.TRUE);
        tableConfig.setSubtableList(new ArrayList<>());
        tableConfig.getSubtableList().add(new TableConfig("devt_model_metadata_field","元数据表字段配置表","form_id","id",Boolean.TRUE));
        tableConfig.getSubtableList().add(new TableConfig("devt_model_metadata_type","模型分类数据","id","type_id",Boolean.TRUE));

        List<TableConfig> tableConfigList=new ArrayList();
        tableConfigList.add(tableConfig);
        HashMap<String,List<Object>> dataMap=new HashMap<>();
        dataMap.put(tableConfig.getTablename(),new ArrayList<>());
        dataMap.get(tableConfig.getTablename()).addAll(Arrays.asList(split));

        DataExportUtil dataExportUtil = DataExportUtil.createDataExportUtil(nbjdbcTemplate.getJdbcTemplate().getDataSource(), true);
        String sqlContent=dataExportUtil.exportData(tableConfigList,dataMap,new ArrayList<>());
        String  contentType="text/sql";
        response.setContentType(StringUtil.isEmptyOrLength0(contentType)?"application/octet-stream":contentType);

        String tableid = tableidlist.replaceAll(",", "_");
        tableid=tableid.indexOf("_")>0?tableid.substring(0,tableid.indexOf("_")):tableid;
        response.addHeader("Content-Disposition","attachment;filename="+java.net.URLEncoder.encode("元数据配置导出_"+tableid +".sql","UTF-8"));
        response.setCharacterEncoding("utf-8");
        InputStream inputStream=new ByteArrayInputStream(sqlContent.getBytes(StandardCharsets.UTF_8));
        byte[] byteData=new byte[1024*1024*3];
        int count=-1;
        ServletOutputStream servletOutputStream= response.getOutputStream();
        while ((count=inputStream.read(byteData))!=-1){
            servletOutputStream.write(byteData,0,count);
        }
        servletOutputStream.flush();
    }
    
    
    
    @RequestMapping("dbSyncInter")
    @ResponseBody
    public Result dbSyncInter(String formId, HttpServletRequest request, HttpServletResponse response) throws Exception{
        try {
            DevtModelMetadataTableEntity metadataTableEntity=metadataTableService.findOne(formId);
            if(metadataTableEntity.getStoretype().equals(EnumUtils.StoreTypeEnum.普通.name())){
                List<DevtModelMetadataFieldEntity> metadataFieldEntities=metadataFieldService.getAllByTid(formId);
                DBTypeUtil.DBTYPE dbtype=DBTypeUtil.getDbtype(dlBaseJdbcTemplate.getDataSource());
                DbTableManager dbTableManager = new DbTableManager(dlBaseJdbcTemplate,dbtype);
                
                StringBuilder updateSql = new StringBuilder();
                String tablesql = dbTableManager.dbsyncTableSql(metadataTableEntity, metadataFieldEntities);
                updateSql.append(tablesql);
                updateSql.append("\r\n");
    
                updateSql.append(" IF EXISTS(SELECT 1 FROM sys.views WHERE name='"+metadataTableEntity.getViewcode()+"') ");
                updateSql.append(" DROP VIEW "+metadataTableEntity.getViewcode()+"; ");
                updateSql.append(" \r\nGO\r\n  ");
                StringBuilder createview = new StringBuilder();
                createview.append(" create view "+metadataTableEntity.getViewcode());
                createview.append(" \r\nas ");
                createview.append(" \r\nselect * ");
                createview.append(" \r\nfrom ").append(metadataTableEntity.getCode()).append(" with(nolock) ");
    
                updateSql.append("\r\n");
                updateSql.append(createview);
                
                return Result.ok("",updateSql);
            }
    
            if(metadataTableEntity.getStoretype().equals(EnumUtils.StoreTypeEnum.json.name())){
                DBTypeUtil.DBTYPE dbtype=DBTypeUtil.getDbtype(dlBaseJdbcTemplate.getDataSource());
                DbTableManager dbTableManager = new DbTableManager(dlBaseJdbcTemplate,dbtype);
                List<DevtModelMetadataFieldEntity> metadataFieldEntities=new ArrayList<>();
                DevtModelMetadataFieldEntity sysModelMetadataFieldEntity=new DevtModelMetadataFieldEntity();
                sysModelMetadataFieldEntity.setFieldType(DbTableManager.FIELDTYPE.STRING.getCode());
                sysModelMetadataFieldEntity.setFieldCode("jsondata");
                sysModelMetadataFieldEntity.setTypeLength(Integer.MAX_VALUE);
                metadataFieldEntities.add(sysModelMetadataFieldEntity);
                
                sysModelMetadataFieldEntity=new DevtModelMetadataFieldEntity();
                sysModelMetadataFieldEntity.setFieldType(DbTableManager.FIELDTYPE.STRING.getCode());
                sysModelMetadataFieldEntity.setFieldCode("id");
                sysModelMetadataFieldEntity.setTypeLength(64);
                sysModelMetadataFieldEntity.setBz("id");
                sysModelMetadataFieldEntity.setPkey(1);
                metadataFieldEntities.add(sysModelMetadataFieldEntity);
    
                sysModelMetadataFieldEntity=new DevtModelMetadataFieldEntity();
                sysModelMetadataFieldEntity.setFieldType(DbTableManager.FIELDTYPE.STRING.getCode());
                sysModelMetadataFieldEntity.setFieldCode("_usercode");
                sysModelMetadataFieldEntity.setTypeLength(256);
                sysModelMetadataFieldEntity.setBz("用户编码");
                metadataFieldEntities.add(sysModelMetadataFieldEntity);
    
                sysModelMetadataFieldEntity=new DevtModelMetadataFieldEntity();
                sysModelMetadataFieldEntity.setFieldType(DbTableManager.FIELDTYPE.DATETIME.getCode());
                sysModelMetadataFieldEntity.setFieldCode("_createtime");
                sysModelMetadataFieldEntity.setTypeLength(64);
                sysModelMetadataFieldEntity.setBz("创建时间");
                metadataFieldEntities.add(sysModelMetadataFieldEntity);
    
                sysModelMetadataFieldEntity=new DevtModelMetadataFieldEntity();
                sysModelMetadataFieldEntity.setFieldType(DbTableManager.FIELDTYPE.DATETIME.getCode());
                sysModelMetadataFieldEntity.setFieldCode("_updatetime");
                sysModelMetadataFieldEntity.setTypeLength(64);
                sysModelMetadataFieldEntity.setBz("更新时间");
                metadataFieldEntities.add(sysModelMetadataFieldEntity);
    
                sysModelMetadataFieldEntity=new DevtModelMetadataFieldEntity();
                sysModelMetadataFieldEntity.setFieldType(DbTableManager.FIELDTYPE.DATETIME.getCode());
                sysModelMetadataFieldEntity.setFieldCode("_datatime");
                sysModelMetadataFieldEntity.setTypeLength(64);
                sysModelMetadataFieldEntity.setBz("更新时间");
                metadataFieldEntities.add(sysModelMetadataFieldEntity);
    
                StringBuilder updateSql = new StringBuilder();
                String tablesql = dbTableManager.dbsyncTableSql(metadataTableEntity, metadataFieldEntities);
                updateSql.append(tablesql);
                updateSql.append("\r\n");
    
                updateSql.append(" IF EXISTS(SELECT 1 FROM sys.views WHERE name='"+metadataTableEntity.getViewcode()+"') ");
                updateSql.append(" DROP VIEW "+metadataTableEntity.getViewcode()+"; ");
                updateSql.append(" \r\nGO\r\n  ");
                StringBuilder createview = new StringBuilder();
                createview.append(" create view "+metadataTableEntity.getViewcode());
                createview.append(" \r\nas ");
                createview.append(" \r\nselect _datatime _datatime , ");
                List<DevtModelMetadataFieldEntity> metadataFieldEntitiereal=metadataFieldService.getAllByTid(formId);
                for (int i = 0; i < metadataFieldEntitiereal.size(); i++) {
                    DevtModelMetadataFieldEntity modelMetadataFieldEntity = metadataFieldEntitiereal.get(i);
                    createview.append(" JSON_VALUE(jsondata,'$."+modelMetadataFieldEntity.getFieldCode()+"') ");
                    createview.append(modelMetadataFieldEntity.getFieldCode());
                    if(i<metadataFieldEntitiereal.size()-1){
                        createview.append(",").append("\r\n");
                    }
                }
                createview.append(" from ").append(metadataTableEntity.getCode()).append(" with(nolock) ");
    
                updateSql.append("\r\n");
                updateSql.append(createview);
                return Result.ok("",updateSql);
            }
            return Result.error("存储方式不存在.");
        }catch (Exception ex){
            logger.error("【执行"+this.getClass().getName()+".dbSyncInter() 方法失败 】异常："+ex.getMessage(),ex);
            
            return Result.error("操作错误，请稍候再试.");
        }
    }
}
